/**
 * json.js: This file defines functions JSON.parse() and JSON.serialize() for
 * decoding and encoding JavaScript objects and arrays from and to
 * application/json format.
 * 
 * The JSON.parse() function is a safe parser: it uses eval() for efficiency but
 * first ensures that its argument contains only legal JSON literals rather than
 * unrestricted JavaScript code.
 * 
 * This code is derived from the code at http://www.json.org/json.js which was
 * written and placed in the public domain by Douglas Crockford.
 */
// This object holds our parse and serialize functions
var JSON = {};

// The parse function is short but the validation code is complex.
// See http://www.ietf.org/rfc/rfc4627.txt
JSON.parse = function(s) {
	try {
		return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(s.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + s + ')');
	} catch (e) {
		return false;
	}
};

// Our JSON.serialize() function requires a number of helper functions.
// They are all defined within this anonymous function so that they remain
// private and do not pollute the global namespace.
(function() {
	var m = { // A character conversion map
		'\b' : '\\b',
		'\t' : '\\t',
		'\n' : '\\n',
		'\f' : '\\f',
		'\r' : '\\r',
		'"' : '\\"',
		'\\' : '\\\\'
	}, s = { // Map type names to functions for serializing those types
		'boolean' : function(x) {
			return String(x);
		},
		'null' : function(x) {
			return "null";
		},
		number : function(x) {
			return isFinite(x) ? String(x) : 'null';
		},
		string : function(x) {
			if (/["\\\x00-\x1f]/.test(x)) {
				x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
					var c = m[b];
					if (c) {
						return c;
					}
					c = b.charCodeAt();
					return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
				});
			}
			return '"' + x + '"';
		},
		array : function(x) {
			var a = [ '[' ], b, f, i, l = x.length, v;
			for (i = 0; i < l; i += 1) {
				v = x[i];
				f = s[typeof v];
				if (f) {
					v = f(v);
					if (typeof v == 'string') {
						if (b) {
							a[a.length] = ',';
						}
						a[a.length] = v;
						b = true;
					}
				}
			}
			a[a.length] = ']';
			return a.join('');
		},
		object : function(x) {
			if (x) {
				if (x instanceof Array) {
					return s.array(x);
				}
				var a = [ '{' ], b, f, i, v;
				for (i in x) {
					v = x[i];
					f = s[typeof v];
					if (f) {
						v = f(v);
						if (typeof v == 'string') {
							if (b) {
								a[a.length] = ',';
							}
							a.push(s.string(i), ':', v);
							b = true;
						}
					}
				}
				a[a.length] = '}';
				return a.join('');
			}
			return 'null';
		}
	};

	// Export our serialize function outside of this anonymous function
	JSON.serialize = function(o) {
		return s.object(o);
	};
})(); // Invoke the anonymous function once to define JSON.serialize()

